﻿using System;
using System.Collections.Generic;
using Internal.KuiHuaBaoDian.Services.Battle;
using Internal.KuiHuaBaoDian.Services.Battle.Data;
using KuiHuaBaoDian.Services.Battle.Entity;

namespace KuiHuaBaoDian.Services.Battle.Data {

    /// <summary>
    /// 战斗复杂数据
    /// </summary>
    public interface IReadOnlyBattleComplexData : IReadOnlyF64ComplexData, IReadOnlyBattleData {

        new IBattleComplexData AsReadWrite();
    }

    /// <summary>
    /// 战斗复杂数据
    /// </summary>
    public interface IValueChangedBattleComplexData : IReadOnlyBattleComplexData, IValueChangedF64ComplexData, IValueChangedBattleData {
    }

    /// <summary>
    /// 战斗复杂数据
    /// </summary>
    public interface IBattleComplexData : IValueChangedBattleComplexData, IComplexData<F64, IBattleFusionData> {

        /// <summary>
        /// 基础值
        /// </summary>
        new IBattleFusionData Base { get; }

        /// <summary>
        /// 系数
        /// </summary>
        new IBattleFusionData Factor { get; }

        /// <summary>
        /// 额外增值
        /// </summary>
        new IBattleFusionData Additional { get; }
    }

    [Implement(typeof(IReadOnlyBattleComplexData))]
    [Implement(typeof(IValueChangedBattleComplexData))]
    [Implement(typeof(IBattleComplexData))]
    public abstract class KHBD_BattleComplexData : KHBD_ComplexData<F64, IBattleFusionData, IBattleData>, IBattleComplexData, IReadOnlyBattleFusionData.IItem, IBattleDataInternal {

        public BattleEntityInstanceID EntityInstanceID { get; private set; }

        protected override void Allocate() {
            base.Allocate();
            m_Base = (IBattleFusionData)Base;
            (m_Base as IBattleFusionDataInternal).SetIsRoot(true);
            m_Factor = (IBattleFusionData)Factor;
            (m_Factor as IBattleFusionDataInternal).SetIsRoot(true);
            m_Additional = (IBattleFusionData)Additional;
            (m_Additional as IBattleFusionDataInternal).SetIsRoot(true);
        }

        protected override void Release() {
            m_Base = null;
            m_Factor = null;
            m_Additional = null;
            EntityInstanceID = BattleEntityInstanceID.Empty;
            base.Release();
        }

        private IBattleFusionData m_Base;
        IBattleFusionData IBattleComplexData.Base {
            get {
                AssertDispose();
                return m_Base;
            }
        }

        private IBattleFusionData m_Factor;
        IBattleFusionData IBattleComplexData.Factor {
            get {
                AssertDispose();
                return m_Factor;
            }
        }

        private IBattleFusionData m_Additional;
        IBattleFusionData IBattleComplexData.Additional {
            get {
                AssertDispose();
                return m_Additional;
            }
        }

        void IBattleDataInternal.EnableFilter(BattleEntityInstanceID entityInstanceID) {
            AssertDispose();
            EntityInstanceID = entityInstanceID;
        }

        protected override F64 Calculate() {
            if (F64.MaxValue == Base.Value || F64.MaxValue == Factor.Value || F64.MaxValue == Additional.Value) {
                return F64.MaxValue;
            } else if (F64.MinValue == Base.Value || F64.MinValue == Factor.Value || F64.MinValue == Additional.Value) {
                return F64.MinValue;
            } else {
                return Base.Value * Factor.Value + Additional.Value; // TODO: 需要处理数字越界
            }
        }

        protected override F64 GetDefaultMaxValue() => F64.MaxValue;

        protected override F64 GetDefaultMinValue() => F64.MinValue;

        protected override F64 Clamp(F64 value, F64 min, F64 max) => F64.Clamp(value, min, max);

        IBattleData IReadOnlyBattleData.AsReadWrite() => throw new NotSupportedException($"{nameof(IReadOnlyBattleData)}.{nameof(IReadOnlyBattleData.AsReadWrite)} 已被 {nameof(IReadOnlyBattleComplexData)}.{nameof(IReadOnlyBattleComplexData.AsReadWrite)} 覆盖");
        IBattleComplexData IReadOnlyBattleComplexData.AsReadWrite() {
            AssertDispose();
            return this;
        }

        bool IReadOnlyBattleFusionData.IItem.ApplyFilter(IEnumerable<IReadOnlyBattleFusionData.IItem> owner, IReadOnlyCollection<IReadOnlyBattleFusionData.IItem> takedItems) {
            AssertDispose();
            return (BattleService.Instance as IBattleServiceInternal).ApplyFusionDataItemFilter(owner, this, takedItems);
        }
    }
}
